package com.boe.common.model;

import com.boe.common.util.StringUtil;
import lombok.*;
import org.springframework.beans.BeanUtils;

import java.sql.JDBCType;

/**
 * 按 Freemarker 形式定义数据库表模型 。
 */
public class TableColumnDetail extends TableColumnMetaData {

    public static TableColumnDetail loadFrom(TableColumnMetaData column) {
        var ret = new TableColumnDetail();
        BeanUtils.copyProperties(column, ret);
        return ret;
    }


    /**
     * 去除（）标志的注释，用于生成 CRUD 前端页面表单的标题
     */
    public String getLabelComment() {
        return this.columnComment.replace("\\s*\\([^)\\s]*\\)\\s*", "");
    }

    public String getFieldName() {
        var name2 = this.columnName;
        if (Character.isDigit(name2.charAt(0))) {
            name2 = "field_" + name2;
        }


        return StringUtil.getSmallCamelCase(name2);
    }

    public java.sql.JDBCType getDbType() {
        var exact = StringUtil.toEnum(this.dataType, JDBCType.class);
        if (exact != null) {
            return exact;
        }

        if (this.dataType.equalsIgnoreCase("datetime")) {
            return JDBCType.TIMESTAMP;
        }

        if (this.dataType.equalsIgnoreCase("int")) {
            return JDBCType.INTEGER;
        }

        throw new RuntimeException("不识别类型: " + this.dataType);
    }

    public String getJavaType() {
        var dbType = getDbType();
        switch (dbType) {
            case BIT:
            case BOOLEAN:
                return "Boolean";
            case TINYINT:
                return "Byte";
            case SMALLINT:
                return "Short";
            case INTEGER:
                return "Integer";
            case BIGINT:
                return "Long";
            case FLOAT:
            case REAL:
                return "Float";
            case DOUBLE:
            case NUMERIC:
            case DECIMAL:
                return "Double";
            case CHAR:
            case VARCHAR:
            case LONGVARCHAR:
            case ROWID:
            case NCHAR:
            case NVARCHAR:
            case LONGNVARCHAR:
            case SQLXML:
                return "String";
            case DATE:
                return "LocalDate";
            case TIME:
                return "LocalTime";
            case TIMESTAMP:
            case TIME_WITH_TIMEZONE:
            case TIMESTAMP_WITH_TIMEZONE:
                return "LocalDateTime";
            case BINARY:
            case VARBINARY:
            case LONGVARBINARY:
            case NULL:
            case OTHER:
            case JAVA_OBJECT:
            case DISTINCT:
            case STRUCT:
            case ARRAY:
            case BLOB:
            case CLOB:
            case REF:
            case DATALINK:
            case REF_CURSOR:
            case NCLOB:
                return "Object";
        }

        return "";
    }

    public String getDefaultValue() {
        var dbType = getDbType();
        switch (dbType) {
            case BIT:
            case BOOLEAN:
                return "false";
            case TINYINT:
            case SMALLINT:
            case INTEGER:
            case BIGINT:
                return "0";
            case FLOAT:
            case REAL:
            case DOUBLE:
            case NUMERIC:
            case DECIMAL:
                return "0.0";
            case CHAR:
            case VARCHAR:
            case LONGVARCHAR:
            case ROWID:
            case NCHAR:
            case NVARCHAR:
            case LONGNVARCHAR:
            case SQLXML:
                return "\"\"";
            case DATE:
                return "LocalDate.min()";
            case TIME:
                return "LocalTime.min()";
            case TIMESTAMP:
            case TIME_WITH_TIMEZONE:
            case TIMESTAMP_WITH_TIMEZONE:
                return "LocalDateTime.min()";
            case BINARY:
            case VARBINARY:
            case LONGVARBINARY:
            case NULL:
            case OTHER:
            case JAVA_OBJECT:
            case DISTINCT:
            case STRUCT:
            case ARRAY:
            case BLOB:
            case CLOB:
            case REF:
            case DATALINK:
            case REF_CURSOR:
            case NCLOB:
                return "null";
        }
        return "null";
    }


    public Boolean getIsAutoId() {
        return this.columnComment.contains("auto_id");
    }

    public Boolean getIsAutoNumber() {
        return this.columnComment.contains("auto_number");
    }

    /*下面四个属性表示该表的单键主键 或 唯一键*/
    public Boolean getIsAutoInc() {
        return this.extra.equals("auto_increment");
    }

    public Boolean getIsEnum() {
        return this.dataType.equals("enum");
    }

    public Boolean getIsEnumSet() {
        return this.dataType.equals("set");
    }

}